#include "../headers/structsystem.h"

using namespace std;



double rampStep(double rtime, double time)
{
    return 1.0;
}

void showParticleMovement(const double arr[])
{
    for (int i = 0; i < 6; i++)
    {
        cout << arr[i] << ", ";
    }
    cout << endl;
}

// void showParticleForce(const vector<double> *v1)
void showParticleForce(const double v1[])
{
    for (int i = 0; i < 6; i++)
    {
        cout << v1[i] << ", ";
    }
    cout << endl;
}



int main()
{
    // create system
    StructSystem system = StructSystem(1);
    system.setJobname("PlasticBeam3D");


    // solve parameters
    double endTime = 20.0;
    double h = 1.0e-4;
    double zeta = 1;
    double p = 0.1;
    double rtime = 50.0;

    // create particles
    Particle * p1 = new Particle(1, 0, 0, 0);
    Particle * p2 = new Particle(2, 0, 0, 10);
    system.addParticle(p1);
    system.addParticle(p2);

    // create material
    // LinearElastic mat = LinearElastic(1);
    UniBilinear mat = UniBilinear(1, 1.0E3, 1.0E2, 20, 0);
    // mat.setE(1.0E6);
    mat.setDensity(1000);
    mat.setNu(0.3);
    // mat.setLimitedTensileStrain(0.0003);

    cout << "G: " << mat.G() << endl;

    // create section
    // Rectangle sect = Rectangle(1, 20, 20);

    // create elements
    // cout << 2 << endl;
    // double ref_node[3] = {0, 0, 100};
    // SectionGridParameter para = {.sections=3, .cells=4, .points=2, .x1=2, .x2=2};
    AngleSteel sect = AngleSteel(1, 40, 20, 2, 2);
    SectionGridParameter para = {.sections=3, .cells=4, .points=1, .x1=2, .x2=2};
    // section info
    PlasticBeam3D * e = new PlasticBeam3D(1, p1, p2, &mat, &sect, para);
    system.addElement(e);

    // constraints
    DOF c1 = {.key = {true, true, true, true, true, true},
              .val = {0, 0, 0, 0, 0, 0}};
    system.addConstraint(1, c1);
    system.info();

    cout << 1 << endl;
    string path = system.workdir() + "/" + system.jobname() + "/model";
    system.saveModel(path);

    StdArray6d f1 {0, 0, 0, 5000, 0, 0};
    // f1[0] = 100;
    // f1[1] = 100;

    system.addExternalForce(2, f1);
    system.solve(h, zeta, true);
    system.setInternalForce();


    int nStep = ceil(endTime / h);
    // int nStep = 100;
    cout << nStep << endl;

    int count = 0;
    int interval = 10000;
    for (int i = 0; i <= nStep; i++)
    {
        // cout << "\n---------- current step: " << i << "----------" << endl;
        system.solve(h, zeta);
        system.clearParticleForce();
        // add external force
        system.setExternalForce(2, f1);
        system.setInternalForce();

        // system.autoKillElement();
        // system.removeFreeParticle();
        // save results
        // if (count % interval == 0)
        if ((count <= 100) | (count % interval == 0))
        {
            string path = system.workdir() + "/" + system.jobname() + "/" +
                          to_string(count);
            system.saveParticleResult(path);
            system.saveElementResult(path);
            system.saveSupportReact(path);
        }
        count++;
        // const double * force1 = p1->getForce();
        // const double * force2 = p2->getForce();

        // cout << "\nTotal Force of Nodes: " << endl;
        // cout << "p1 force: ";
        // for (int i = 0; i < 6; i++)
        // {
        //     cout << force1[i] << ", ";
        // }
        // cout << endl;

        // cout << "p2 force: ";
        // for (int i = 0; i < 6; i++)
        // {
        //     cout << force2[i] << ", ";
        // }
        // cout << endl;
    }

    system.releaseContainers();
    return 0;
}